﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.IO;
using System.Collections;

namespace SqlServerPacker {
	internal class IISManager {
		/// <summary>
		/// 安装文件名列表
		/// </summary>
		protected List<string> files = new List<string>();

		public string OperatingSystem { get; set; }
		private string[] requiredSuffix;
		/// <summary>
		/// 需要的安装文件后缀
		/// </summary>
		protected string[] RequiredSuffix {
			get {
				if (requiredSuffix == null) {
					switch (OperatingSystem) {
						case "Microsoft Windows XP":
							requiredSuffix = new string[] { ".dll", ".ini", ".h2", ".exe", ".ocx", ".msc", ".pmc", ".sql", ".cab", ".vbs", ".hlp", ".cnt" };
							break;
						case "Microsoft Windows Server 2003":
						case "Microsoft Windows Server 2003 R2":
							requiredSuffix = new string[] { ".dll", ".ini", ".h2", ".exe", ".ocx", ".msc", ".pmc", ".sql", ".cab", ".vbs", ".hlp", ".cnt", ".wsc", ".mfl", ".mof", ".asp" };
							break;
					}
				}
				return requiredSuffix;
			}
			set {
				requiredSuffix = value;
			}
		}
		private char[] separatorChars = new char[] { ',', '|', ';', '\t', '\\', '/', ' ', '\"', '=' };
		/// <summary>
		/// Inf文件内容分隔符
		/// </summary>
		protected char[] SeparatorChars {
			get { return separatorChars; }
			set { separatorChars = value; }
		}

		protected string IISInfPath { get; set; }
		protected string I386PackSourcePath { get; set; }
		protected string TargetPath { get; set; }

		/// <summary>
		/// 获取IIS必需文件
		/// </summary>
		/// <param name="operatingSystem">操作系统名称</param>
		/// <param name="infPath">Inf文件路径</param>
		/// <param name="sourcePath">I386源文件路径（路径需包含\i386）</param>
		/// <param name="batPath">要生成的Bat文件路径</param>
		internal IISManager(string operatingSystem, string infPath, string sourcePath, string batPath) {
			this.OperatingSystem = operatingSystem;
			this.IISInfPath = infPath;
			this.I386PackSourcePath = sourcePath;
			this.TargetPath = batPath;
		}

		#region GetRequiredFiles
		/// <summary>
		/// 查找文件是否存在（包含：.DLL->.DL_或者.DLL）
		/// </summary>
		/// <param name="sourcePath">查找目标路径</param>
		/// <param name="fileName">被查找的文件名</param>
		/// <returns>返回查找到的文件路径，如果没找到返回空字符串</returns>
		private string FindFile(string sourcePath, string fileName) {
			string[] strList = Directory.GetFiles(sourcePath, fileName, SearchOption.AllDirectories);
			if (strList != null && strList.Length > 0)
				return strList[0];


			string extName = Path.GetExtension(fileName);
			if (extName.Length == 4) {
				fileName = fileName.Substring(0, fileName.Length - 1) + "_";
			}
			else if (extName.Length < 4) {
				if (extName.StartsWith(".")) {
					fileName = fileName + "_";
				}
				else {
					fileName = fileName + "._";
				}
			}
			else {
				throw new Exception(fileName);
			}

			strList = Directory.GetFiles(sourcePath, fileName, SearchOption.AllDirectories);
			if (strList != null && strList.Length > 0)
				return strList[0];
			return "";
		}
		/// <summary>
		/// 获得IIS安装必备文件并写入Bat文件中
		/// </summary>
		internal string GetRequiredFiles() {
			//获取IIS必需文件



			FileInfo inf = new FileInfo(IISInfPath);
			FileStream stream = inf.OpenRead();
			StreamReader reader = new StreamReader(IISInfPath);
			List<string> components = new List<string>();


			while (!reader.EndOfStream) {
				string line = reader.ReadLine();
				if (line.StartsWith("Copyfiles")) {
					string files = line.Substring(10);

					while (files.EndsWith("\\")) {
						files = files.TrimEnd('\\');
						files += reader.ReadLine();
					}
					components.AddRange(files.Split(','));

				}
			}
			for (int i = 0; i < components.Count; i++) {
				components[i] = string.Format("[{0}]", components[i].Trim());
			}

			List<string> copyfiles = new List<string>();
			List<string> i386files = new List<string>();


			StreamReader readerFiles = new StreamReader(IISInfPath);
			bool needRead = true;
			string option = string.Empty;
			while (!readerFiles.EndOfStream) {
				if (needRead) {
					option = readerFiles.ReadLine();
				}



				if (components.IndexOf(option) > -1) {

					option = readerFiles.ReadLine();
					while (!option.StartsWith("[")) {
						if (option.Trim() != string.Empty) {
							if (option.IndexOf(',') > -1) {
								i386files.AddRange(option.Split(','));
							}
							else {
								i386files.Add(option);
							}
						}
						option = readerFiles.ReadLine();
						needRead = !option.StartsWith("[");
					}
				}
				else {
					needRead = true;
				}
			}
			//var test1 = new List<string>(i386files.Distinct(new compear()));

			foreach (string item in i386files) {
				CopyFilesWithSubTree(item, I386PackSourcePath);
			}
			return string.Empty;

			string[] iisInfPath = File.ReadAllLines(IISInfPath);
			for (int i = 0; i < iisInfPath.Length; i++) {
				string[] separatorList = iisInfPath[i].Split(SeparatorChars);
				for (int j = 0; j < separatorList.Length; j++) {
					foreach (string suffix in RequiredSuffix) {
						if (separatorList[j].Contains(suffix)) {
							files.Add(separatorList[j]);
						}
					}
				}
			}
			//写入Bat文件
			int count = 0;
			for (int i = 0; i < files.Count; i++) {
				string filePath = FindFile(I386PackSourcePath, files[i]);
				StringBuilder batStr = new StringBuilder();
				if (!string.IsNullOrEmpty(filePath)) {
					//File.Copy(filePath, targetPath);
					batStr.AppendLine(string.Format("copy %1\\{0} %2\\{1} /y", Path.GetFileName(filePath), Path.GetFileName(filePath)));
					count++;
				}
				File.WriteAllText(TargetPath, batStr.ToString());
			}
			return count + "/" + files.Count;
		}

		private void CopyFilesWithSubTree(string filename, string i386Path) {
			string filePath = FindFile(Path.Combine(i386Path, "I386"), filename);
			if (filePath == string.Empty) {
				filePath = FindFile(Path.Combine(i386Path, "amd64"), filename);
			}
			if (filePath == string.Empty) {
				return;
			}
			string subPath = Path.GetDirectoryName(filePath).Replace(i386Path, "");
			string target = Path.Combine(TargetPath, subPath);
			if (!Directory.Exists(target)) {
				Directory.CreateDirectory(target);
			}
			target = Path.Combine(target, Path.GetFileName(filePath));
			if (File.Exists(target)) {
				return;
			}
			File.Copy(filePath, target);
		}
		#endregion
	}

	class compear : IEqualityComparer<string> {
		public bool Equals(string x, string y) {
			return x.Equals(y, StringComparison.CurrentCultureIgnoreCase);
		}

		public int GetHashCode(string obj) {
			return obj.GetHashCode();
		}
	}

}
